package org.example.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import org.example.entity.JsonMapper;



import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
 * ============================================================<br>
 * <p> ProjectName ：dianguanjiaexportdata </p >
 * <p> @author lz </p >
 * <p> @date 2023/3/16 </p >
 * <p> @version ：1.0 </p >
 * ============================================================<br>
 * <p>
 * ${description}
 * </p >
 * ============================================================<br>
 */
public class JsonService {
    
    /*public static void main(String[] args) {
        String str = "{\"ciId\":\"01ed11faae9e4315949b255ac8975922\",\"ciNo\":\"DGJ-CZXX2023000002\",\"custId\":\"A483A7FC738645AF987EBA0B1F8B0D32\",\"custNo\":\"2023030800001\",\"custName\":\"献县达义车架厂\",\"servicerId\":\"cb0749b9ca97b0b98e91d0e6f7f5dfac\",\"servicerName\":\"沧州献县中兴\",\"ciName\":\"献县达义车架厂\",\"orgNo\":\"1340317\",\"orgName\":\"献县\",\"addCustName\":\"\",\"ciCity\":\"13403\",\"ciCounty\":\"1340317\",\"ciCityName\":\"沧州市\",\"ciCountyName\":\"献县\",\"consNo\":null,\"consNoView\":null,\"ciSettlModel\":null,\"ciSettlModelName\":null,\"voltCode\":null,\"voltCodeName\":null,\"voltCodeNameView\":null,\"ciSetMeal\":\"23\",\"ciSetMealName\":\"星会员套餐\",\"ciYear\":\"12\",\"ciMoney\":\"1500\",\"ciContractState\":\"06\",\"ciContractStateName\":null,\"ciPaymentState\":\"01\",\"ciPaymentStateName\":null,\"ciBillState\":\"01\",\"ciBillStateName\":null,\"ciServiceState\":null,\"ciServiceStateName\":null,\"ciSignDate\":\"2022-03-30\",\"ciEffectDate\":null,\"ciExpireDate\":null,\"serviceBgn\":null,\"serviceEnd\":null,\"serviceBgnEnd\":\"——\",\"contractCap\":null,\"beginMoney\":\"1500\",\"socEmpNo\":\"\",\"promoteState\":null,\"remark\":\"\",\"createUser\":\"HB_LIUYARUI\",\"createTime\":null,\"subDate\":null,\"tranDate\":null,\"ciLetterDate\":null,\"submission\":\"——\",\"turnOver\":\"——\",\"issue\":\"——\",\"instalstateDate\":\"——\",\"totalPayMoney\":0,\"totalBillMoney\":0,\"entrustingParty\":\"献县达义车架厂\",\"supplierSide\":null,\"isRenew\":null,\"isRenewName\":null,\"ifInstal\":null,\"ifInstalName\":null,\"contractNum\":\"1\",\"contactName\":\"邵昆岩\",\"mobile\":\"13292728855\",\"postYear\":null,\"installContact\":null,\"installMobile\":null,\"installAddr\":null,\"otherThreatyContent\":null,\"consNum\":0,\"inspectionNum\":2,\"inspectionExecunum\":0,\"ctrtEquips\":[{\"ctrtEquipId\":\"d3fa3e89f6fe48e5af792d8f5003a381\",\"equipType\":\"1401\",\"equipParaNo\":\"200\",\"equipSeriesNo\":null,\"consNo\":null,\"repairCount\":\"5\",\"repairExecunum\":\"0\",\"equipFilezInfoId\":\"1babc9ae2f5147c984ad7feae671245d\",\"equipName\":\"1号变压器\",\"elecLv\":\"01\",\"elecLvName\":\"10kV\",\"installType\":\"02\",\"installTypeName\":\"杆变\",\"ppId\":\"8\",\"checked\":false}],\"contractBillAndPaymentString\":[],\"paymentPerList\":null,\"accountNo\":\"cz_xxdy\",\"ciBusinessType\":\"02\",\"custType\":\"05\",\"instalstateName\":null,\"consList\":[],\"priceList\":[{\"cpId\":\"3494f366491c445c9ca24fdf6237f100\",\"ppId\":\"5\",\"priceType\":\"05\",\"priceTypeName\":\"慧计量套餐\",\"price\":0,\"priceString\":null,\"uint\":\"03\",\"uintName\":\"元/年/用电户号\",\"repairCount\":0,\"exceedPrice\":0,\"exceedUint\":\"02\",\"exceedUintName\":\"元/次\"},{\"cpId\":\"9497cfa9798148c28471d3c5b649805e\",\"ppId\":\"8\",\"priceType\":\"02\",\"priceTypeName\":\"160（不含）至315（含315）\",\"price\":1500,\"priceString\":null,\"uint\":\"01\",\"uintName\":\"元/年/台变压器\",\"repairCount\":5,\"exceedPrice\":400,\"exceedUint\":\"02\",\"exceedUintName\":\"元/次\"}]}";
        
        System.out.println(createTableSqlByJson(str));
        
    }*/
    /**
     * 根据Json返回字符串创建表语句
     * @param jsonParam
     * @return
     */
    public static String createTableSqlByJson(String jsonParam) {
        List<JsonMapper> analysisResult = analysisJson(jsonParam);
        if (CollectionUtils.isNotEmpty(analysisResult)) {
            //Map<String, List<JsonMapper>> mapperByParentName = analysisResult.stream().collect(Collectors.groupingBy(JsonMapper::getParentName));
            Map<String, List<String>> mapperByParentName = analysisResult.stream().collect(Collectors.groupingBy(JsonMapper::getParentName,
                    Collectors.mapping(JsonMapper::getCurrName, Collectors.toList())));
            Iterator iterator = mapperByParentName.entrySet().iterator();
            String sql = "";
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                sql = sql + createSql(entry.getKey().toString(), (List<String>) entry.getValue());
            }
            return sql;
        }
        return null;
    }
    
    
    
    /**
     * Jackson 解析json
     * @param jsonParam
     * @return
     */
    public static List<JsonMapper> analysisJson(String jsonParam) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode jsonNodeRoot = mapper.readTree(jsonParam);
            List<JsonMapper> tableMapper = new ArrayList<>();
            List<JsonMapper> fieldMapper = new ArrayList<>();
            recursiveAnalysis(tableMapper, fieldMapper, "rootJson",jsonNodeRoot);
            
            
            
            // 表与表之间
            if (CollectionUtils.isNotEmpty(tableMapper)) {
                // 合并
                fieldMapper.addAll(tableMapper);
                /*for (JsonMapper jsonMapper : tableMapper){
                    System.out.println(jsonMapper.getParentName() + "===111===" +jsonMapper.getCurrName());
                }*/
            }
            
            
            
            // 属性与表之间
            if (CollectionUtils.isNotEmpty(fieldMapper)) {
                
                
                
                // 去重
                List<JsonMapper> fieldMapperAfter = fieldMapper.stream().collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(
                                Comparator.comparing(o -> o.getParentName() + ";" + o.getCurrName()))), ArrayList::new));
                
                
                
                // 排序
                Collections.sort(fieldMapperAfter, new Comparator<JsonMapper>(){
                    @Override
                    public int compare(JsonMapper o1, JsonMapper o2) {
                        return o1.getParentName().compareTo(o2.getParentName());// 按照父节点升序
                    }
                });
                /*for (JsonMapper jsonMapper : fieldMapperAfter){
                    System.out.println(jsonMapper.getParentName() + "======" +jsonMapper.getCurrName());
                }*/
                return fieldMapperAfter;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    
    
    /**
     *  Jackson 递归解析子节点
     * @param tableMapper 表与表之间关联映射
     * @param fieldMapper 字段属性与表之间关联映射
     * @param parentNodeName 父节点名称
     * @param jsonNode 当前节点
     */
    public static void recursiveAnalysis(List<JsonMapper> tableMapper,List<JsonMapper> fieldMapper, String parentNodeName,JsonNode jsonNode) {
        if (jsonNode.isContainerNode()){
            if (JsonNodeType.OBJECT == jsonNode.getNodeType()) {
                Iterator<String> fieldNames = jsonNode.fieldNames();
                while (fieldNames.hasNext()) {
                    String fieldName = fieldNames.next();
                    if (jsonNode.get(fieldName).isContainerNode()){
                        //System.out.println("父对象：" +parentNodeName +"当前对象的名称：" + fieldName);
                        tableMapper.add(new JsonMapper(parentNodeName, fieldName));
                        recursiveAnalysis(tableMapper, fieldMapper, fieldName, jsonNode.get(fieldName));
                    } else {
                        //System.out.println("父属性：" +parentNodeName +"当前属性的名称：" +fieldName + "===" + jsonNode.get(fieldName).getNodeType());
                        fieldMapper.add(new JsonMapper(parentNodeName, fieldName + ":" + jsonNode.get(fieldName).getNodeType()));
                    }
                }
            } else if (JsonNodeType.ARRAY == jsonNode.getNodeType()) {
                Iterator<JsonNode> jsonNodeElements = jsonNode.iterator();
                while (jsonNodeElements.hasNext()) {
                    JsonNode jsonNodeElement = jsonNodeElements.next();
                    recursiveAnalysis(tableMapper, fieldMapper, parentNodeName, jsonNodeElement);
                }
            }
        }
    }
    
    
    
    /**
     * 获取创建表前缀，根据拆分表数字
     * @param tableName
     * @param splitNum
     * @return
     */
    public static String getTablePrefix(String tableName, int splitNum) {
        if (splitNum > 0) {
            tableName = tableName + "_" + splitNum;
        }
        StringBuilder tablePrefix = new StringBuilder();
        tablePrefix.append("CREATE TABLE `"+tableName+"` ( \r\n");
        tablePrefix.append("  `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键', \r\n");
        return tablePrefix.toString();
    }
    
    
    
    /**
     * 获取创建表后缀
     * @param tableName
     * @return
     */
    public static String getTableSuffix(String tableName) {
        StringBuilder tableSuffix = new StringBuilder();
        tableSuffix.append("PRIMARY KEY (`id`), \r\n");
        tableSuffix.append(") ENGINE=InnoDB DEFAULT CHARSET=UTF8; \r\n");
        tableSuffix.append(" \r\n");
        return tableSuffix.toString();
    }
    /**
     *  根据表名以及列名称创建表结构
     * @param tableName
     * @param columnNames
     * @return
     */
    public static String createSql(String tableName, List<String> columnNames) {
        
        
        
        boolean isSplit = isSplitToTables(columnNames.size());
        
        
        
        StringBuilder sqlAll = new StringBuilder();
        sqlAll.append(getTablePrefix(tableName, 0));
        for (int i = 0; i < columnNames.size(); i++) {
            if (columnNames.get(i).contains(":")) {
                String str[] = columnNames.get(i).split(":");
                String columnType = buildColumnType(str[1]);
                sqlAll.append("  `"+str[0]+"` "+columnType+" DEFAULT NULL, \r\n");
            }else {
                sqlAll.append("  `"+columnNames.get(i)+"` LONGTEXT DEFAULT NULL, \r\n");
            }
            if (isSplit) {
                if (i > 0 && i % 50 == 0) {
                    sqlAll.append(getTableSuffix(tableName));
                    sqlAll.append(getTablePrefix(tableName, i / 50));
                }
            }
        }
        sqlAll.append(getTableSuffix(tableName));
        return sqlAll.toString();
    }
    
    
    
    /**
     * 根据json 字段类型构建数据库字段类型
     * 默认 varchar(20)
     * @param jsonType
     */
    public static String buildColumnType(String jsonType) {
        if (JsonNodeType.BOOLEAN.toString().equals(jsonType)) {
            return "CHAR(1)";
        } else if (JsonNodeType.NUMBER.toString().equals(jsonType)) {
            if (jsonType.contains(".")) {
                return "VARCHAR(20)";
            }
            return "INT(11)";
        } else if (JsonNodeType.STRING.toString().equals(jsonType)) {
            return "VARCHAR(100)";
        } else {
            return "VARCHAR(20)";
        }
    }
    
    
    
    /**
     * 根据表的列数判断是否需要拆分字段到多个表
     * 当字段 > 80 时，自动创建多表，多表采用单表 50个字段进行分拆
     * @param columns
     * @return
     */
    public static boolean isSplitToTables(int columns){
        if (columns >= 80) {
            return true;
        }
        return false;
    }

}
